class MonSweeperMut extends Mutator
	Config(UnitedMut);

var	globalconfig	int				SelfDestructTime,CheckInterval,OneSecondProlongDamageThreshhold;
var	globalconfig	array<string>	Untouchable;

var Pawn SweepKiller; // чтобы не вылетали ошибки обращения к LastDamagedBy, будем убивать от имени этого павна

struct MonsterSweepInfo
{
	var	Monster	Mon;
	var	int		SelfDestructTimer;
	var	int		OldHealth;
};

struct UntouchableClass
{
	var	class<Monster>	MonClass;
};

var	array<MonsterSweepInfo>	PendingMonsters;
var	array<UntouchableClass>	UntouchableList;
var	MonSweeperRules			R;

var	int	SweepedMonsters;

replication
{
	reliable if ( Role == ROLE_Authority )
		SweepedMonsters;
}
//--------------------------------------------------------------------------------------------------
simulated function PostBeginPlay()
{
	local int i,n;
	local class<Monster>	TClass;
	local Monster			TMon;

	Super.PostBeginPlay();

	// Спавним правила игры, которые помогут очищать список "трупов"
	R = Spawn(class'MonSweeperRules');
	R.MutatorOwner = Self;

	// Заполняем список "неприкасаемых". Чистильщик не будет убивать неприкасаемых.

	n = Untouchable.Length;

	for(i=0; i<n; i++)
	{
		TClass = class<Monster>(DynamicLoadObject(Untouchable[i],Class'Class'));
		if ( TClass != none )
		{
			UntouchableList.Insert(0,1);
			UntouchableList[0].MonClass = TClass;
		}
	}

	// Заполняем список мобами, которые были заспавнены до активации мутатора (а вдруг такое возможно)
	foreach DynamicActors(class'Monster',TMon)
	{
		if ( bCanBeKilled(TMon.Class) )
		{
			PendingMonsters.Insert(0,1);
			PendingMonsters[0].Mon = TMon;
			PendingMonsters[0].OldHealth = TMon.Health;
		}
	}
	if (SweepKiller==none) SweepKiller=Spawn(class'FakePlayerPawn');
	SweepKiller.bHidden=true;

	SetTimer(float(CheckInterval),true);
}
//--------------------------------------------------------------------------------------------------
simulated function Timer()
{
	local int i;
	local Controller C;
	local KFGameType KFGT;

	for(i=0; i<PendingMonsters.Length; i++)
	{
		if (PendingMonsters[i].Mon==none || PendingMonsters[i].Mon.Controller==none)
		{
			PendingMonsters.Remove(i,1);
			i--;
			continue;
		}
		if ( PendingMonsters[i].OldHealth - PendingMonsters[i].Mon.Health > OneSecondProlongDamageThreshhold * CheckInterval )
		{
			PendingMonsters[i].OldHealth = PendingMonsters[i].Mon.Health;
			PendingMonsters[i].SelfDestructTimer = 0;
		}
		else
		{
			PendingMonsters[i].SelfDestructTimer += CheckInterval;
			if ( PendingMonsters[i].SelfDestructTimer > SelfDestructTime )
			{
				if (Level.Game!=none)
				{
					KFGT=KFGameType(Level.Game);
					if (KFGT!=none)
					{
						if (KFMonster(PendingMonsters[i].Mon)!=none)
						{

							KFMonster(PendingMonsters[i].Mon).LastDamagedBy=SweepKiller;
							PendingMonsters[i].Mon.Controller.Destroy();
							PendingMonsters[i].Mon.Destroy(); //if ( KFGT.KillZed(PendingMonsters[i].Mon.Controller) )
							SweepedMonsters++;
						}
					}
				}
			}
		}
	}
	// в конце игры говорит сколько всего монстров было убито с помощью MonSweeper
	if (Level.Game!=none)
	{
		KFGT=KFGameType(Level.Game);
		if (KFGT!=none)
		{
			if ( KFGT.IsInState('MatchOver') )
			{
				for(C=Level.ControllerList; C!=None && C.Pawn!=None; C=C.NextController)
				{
					C.Pawn.ClientMessage(string(SweepedMonsters) $ " monsters was obliterated by MonsterSweeperMut.");
				}
				SetTimer(0.0,false);
			}
		}
	}
}
//--------------------------------------------------------------------------------------------------
function bool CheckReplacement(Actor Other, out byte bSuperRelevant)
{
	if ( Monster(Other) != none )
	{
		if ( bCanBeKilled(class<Monster>(Other.Class)) )
		{
			PendingMonsters.Insert(0,1);
			PendingMonsters[0].Mon = Monster(Other);
			PendingMonsters[0].OldHealth = Monster(Other).Health;
		}
	}
	return true;
}
//--------------------------------------------------------------------------------------------------
function bool bCanBeKilled(class<Monster> MC)
{
	local int i;

	for(i=0; i<UntouchableList.Length; i++)
	{
		if ( MC == UntouchableList[i].MonClass )
			return false;
	}
	return true;
}
//--------------------------------------------------------------------------------------------------
function bool MustBeKilled(Monster Victim)
{
	local int i;

	if ( !bCanBeKilled(Victim.Class) )
	{// монстр в списке неубиваемых (поидее до сюда не должно)
		return true;
	}
	// монстр обычный смертный
	for(i=0; i<PendingMonsters.Length; i++)
	{
		if ( PendingMonsters[i].Mon == Victim )
		{
			PendingMonsters.Remove(i,1);
			return false;
		}
	}

	//log("MonsterSweeperMut: Error, monster of correct class wasn't registered.");
	return false; // Вроде бы не неприкасаемый, но в списке не значится. Мутатор работает некорректно
}
//--------------------------------------------------------------------------------------------------
function Destroyed()
{
	PendingMonsters.Remove(0,PendingMonsters.Length);

	if ( R != none )
	{
		R.Destroyed();
		R.Destroy();
	}
	Super.Destroyed();
}
//--------------------------------------------------------------------------------------------------
defaultproperties
{
	bAddToServerPackages = True
	GroupName = "KF-MonsterSweeper"
	FriendlyName = "Mon Sweeper"
	Description = "Kills every stuck monster when its existance is too long."
	bAlwaysRelevant = True
	//RemoteRole = ROLE_SimulatedProxy

	SelfDestructTime = 180
	OneSecondProlongDamageThreshhold = 50
	CheckInterval = 1

	Untouchable(0) = "KFChar.ZombieBoss"
}